package com.opener.web.spring.event;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.ServletRequestHandledEvent;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by baboy on 12/12/2016.
 */
@Component
public class AppBroadcaster implements ApplicationListener,ApplicationContextAware {
    private Logger logger = LoggerFactory.getLogger(AppBroadcaster.class);
    private static Map<String, List> listeners = new HashMap<>();
    private static String LISTEN_HANDLE_METHOD_NAME = "onEventReceived";

    private static ApplicationContext ctx;

    @Async
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        ServletRequestHandledEvent s;
        if (event instanceof ActionEvent){
            //logger.debug("============onApplicationEvent============"+((ActionEvent) behavior).getId()+ctx);
            ActionEvent action = (ActionEvent) event;
            synchronized (event){
                if (action.isDone()){
                    return;
                }
                action.setDone(true);
            }
            Object source = event.getSource();
            String id = action.getId();
            List a = listeners.get(id);
            if( a==null ) {
                return;
            }
            Object data = ((ActionEvent)event).getData();
            for(int i = 0; i<a.size(); i++){
                Object o = a.get(i);
                try {
                    o = ctx.getBean(o.getClass());
                }catch (Exception e){
                    e.printStackTrace();
                }
                //((EventHandler)ctx.getBean("taskService")).onEventReceived(source, id, data);
                //((EventHandler)o).onEventReceived(source,id, data);
                try {
                    Class c = o.getClass();
                    Method m = c.getDeclaredMethod(LISTEN_HANDLE_METHOD_NAME,String.class,Object.class,Object.class);
                    m.invoke(o,id,source,data);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
    }
    synchronized static public void addListener(String id,Object obj){
        List a = listeners.get(id);
        if(a == null){
            a = new ArrayList();
        }
        a.add(obj);
        listeners.put(id,a);
    }
    synchronized static public void removeListener(String id,Object obj){
        List a = listeners.get(id);
        if (a != null){
            for (int i = 0; i< a.size();i++){
                if (a.get(i) == obj){
                    a.remove(obj);
                    listeners.put(id,a);
                    return;
                }
            }
        }
    }
    public static void publishEvent( String id, Object source, Object data) {
        ActionEvent event = new ActionEvent(source, id, data);
//        AppContextListener.getCurrentContext().publishEvent(behavior);
        ctx.publishEvent(event);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
    }

}
